﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Eventing.Reader;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MvCameraControl;

namespace CLVisionCameraControl
{
    //海康相机常规的系列，主要Gige、USB接口等的面阵相机
    public class HIKAreaScanCamera : HIKCameraBase
    {
        //=======================              ========================
        /// <summary>
        /// 相机图像回调
        /// </summary>
        public override event Action<IImage> EventGrabBackHIKImage;
        public override event Action<Bitmap> EventGrabBackBitmapImage;

        /// <summary>
        /// 用于显示图像的句柄
        /// </summary>
        public override IntPtr HWnd { get; set; }

        /// <summary>
        /// 相机信息接口    
        /// </summary>
        public override ICLVisionCameraInfo CLVisionCameraInfo { get; set; }

        private IDevice device = null;
        public IDevice Device { get => device; set => device = value; }

        IDeviceInfo _deviceInfo = null;
        public IDeviceInfo DeviceInfo { get => _deviceInfo; set => _deviceInfo = value; }
        public override bool IsOpen { get; set; }
        public override Bitmap OutBMPImage { get; set; }

        bool isGrabbing = false;

        //==============================        ===========================================

        public HIKAreaScanCamera(IDeviceInfo deviceInfo)
        {
            _deviceInfo = deviceInfo;

        }

        public void CreatDevice(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CreatDevice)}: Start!";
            try
            {
                //创建相机设备
                device = DeviceFactory.CreateDevice(_deviceInfo);
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CreatDevice)}: Fail! 创建相机设备失败！" + ex.Message;
            }

            try
            {
                CLVisionCameraInfo = new HIKCameraInfo
                {
                    //将相机信息存储到接口
                    SerialNumber = _deviceInfo.SerialNumber,
                    UserDefinedName = _deviceInfo.UserDefinedName,
                    CameraBrand = "HIK",
                    CameraType = "AreaScan"
                };

                if (_deviceInfo.TLayerType == DeviceTLayerType.MvGigEDevice || _deviceInfo.TLayerType == DeviceTLayerType.MvVirGigEDevice || _deviceInfo.TLayerType == DeviceTLayerType.MvGenTLGigEDevice)
                {
                    IGigEDeviceInfo gigeDevInfo = _deviceInfo as IGigEDeviceInfo;
                    uint nIp1 = ((gigeDevInfo.CurrentIp & 0xff000000) >> 24);
                    uint nIp2 = ((gigeDevInfo.CurrentIp & 0x00ff0000) >> 16);
                    uint nIp3 = ((gigeDevInfo.CurrentIp & 0x0000ff00) >> 8);
                    uint nIp4 = (gigeDevInfo.CurrentIp & 0x000000ff);
                    CLVisionCameraInfo.Ip = string.Format("{0}.{1}.{2}.{3}", nIp1, nIp2, nIp3, nIp4);
                }
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CreatDevice)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CreatDevice)}: Fail! 获取相机设备信息失败！" + ex.Message;
            }
        }
        public override void OpenDeviceByUserDefinedName(string userDefinedName, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByUserDefinedName)}: Start!";
            try
            {

                device = DeviceFactory.CreateDevice(_deviceInfo);
                if (null == device)
                catch (Exception ex)
                catch (Exception ex)
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByUserDefinedName)}: Fail! 创建相机设备失败！";
                    ErrorCode = -1;
                    ErrorText = "Create Device  fail! " + ex.Message;
                    return;
                if (ErrorCode == -1)
                {
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByUserDefinedName)}: Fail! " + "打开相机设备失败！";
                    return;
                }
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByUserDefinedName)}: End!";
            }

            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByUserDefinedName)}: Fail! " + ex.Message;
            }
        }

        public override void OpenDeviceBySerialNumber(string serialNumber, out int ErrorCode, out string ErrorText)
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceBySerialNumber)}: Start!";

            ErrorCode = 0;
            ErrorText = string.Empty;
                device = DeviceFactory.CreateDevice(_deviceInfo);
                if (null == device)
                }
                catch (Exception ex)
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceBySerialNumber)}: Fail! 创建相机设备失败！";
                    ErrorCode = -1;
                    ErrorText = "Create Device  fail! " + ex.Message;
                    return;
                if (ErrorCode == -1)
                {
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceBySerialNumber)}: Fail! " + "打开相机设备失败！";
                    return;
                }
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceBySerialNumber)}: End!";
            }

            }
            catch (Exception ex)
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceBySerialNumber)}: Fail! 创建相机设备失败！ " + ex.Message;
                return;
                ErrorCode = -1;
                ErrorText = "OpenDeviceBySerialNumber fail!" + ex.Message;
            }


        }
        public override void OpenDeviceByIp(string cameraIp, string netExport, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByIp)}: Start!";
            try
            {
                try
                {
                    device = DeviceFactory.CreateDeviceByIp(cameraIp, netExport);
                    if (null == device)
                    {
                        ErrorCode = -1;
                        ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByIp)}: Fail! 创建相机设备失败！";
                        return;
                    if (ErrorCode == -1)
                    {
                        ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByIp)}: Fail! " + "打开相机设备失败！";
                        return;
                    }
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByIp)}: End!";
                }

                }
                catch (Exception ex)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByIp)}: Fail! 创建相机设备失败！" + ex.Message;
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDeviceByIp)}: Fail! " + ex.Message;
            }
        }

        private void OpenDevice(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDevice)}: Start!";

            int result = device.Open();
            if (result != MvError.MV_OK)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDevice)}: Open Device fail! ";
                return;
            }
            IsOpen = true;

            try
            {
                //ch: 判断是否为gige设备 | en: Determine whether it is a GigE device
                if (device is IGigEDevice)
                {
                    //ch: 转换为gigE设备 | en: Convert to Gige device
                    IGigEDevice gigEDevice = device as IGigEDevice;

                    // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                    int optionPacketSize;
                    result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
                    if (result != MvError.MV_OK)
                    {
                        ErrorCode = -1;
                        ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDevice)}: Get Packet Size failed!";
                        return;
                    }
                    else
                    {
                        result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
                        if (result != MvError.MV_OK)
                        {
                            ErrorCode = -1;
                            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDevice)}: Set Packet Size failed!";
                            return;
                        }
                    }
                }

                result = device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(OpenDevice)}: Set AcquisitionMode Continuous failed!";
                    return;
                }
                    device.Parameters.SetEnumValueByString("TriggerMode", "Off");
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = ex.Message;
                return;
            }

            //注册相机回调
            //  RegisterGrabCallback();



        }
        public override void CloseDevice(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CloseDevice)}: Start!";
            try
            {
                int result = device.StreamGrabber.StopGrabbing();
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CloseDevice)}: Fail! Stop Grabbing Fail!";
                    return;
                }
                else
                {
                    isGrabbing = false;
                    IsOpen = false;
                }

                if (Device != null)
                {
                    Device.Close();
                    Device.Dispose();
                }
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CloseDevice)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(CloseDevice)}: Fail! " + ex.Message;
            }
            finally
            {
                SDKSystem.Finalize();
            }
        }


        public override void GetParamExposure(out float exposureTime, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(GetParamExposure)}: Start!";
            exposureTime = 0;
            IFloatValue floatValue;
            try
            {
                int result = device.Parameters.GetFloatValue("ExposureTime", out floatValue);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(GetParamExposure)}: Fail! Get Exposure Time Fail!";
                    return;
                }
                exposureTime = (float)floatValue.CurValue;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(GetParamExposure)}: End!";
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = $"{nameof(HIKAreaScanCamera)}.{nameof(GetParamExposure)}: Fail! " + ex.Message;
            }
        }

        public override void GetParamFrameRate(out float frameRate, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            frameRate = 0;
            IFloatValue floatValue;
            try
            {
                int result = device.Parameters.GetFloatValue("ResultingFrameRate", out floatValue);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Get FrameRate Fail!";
                    return;
                }

                frameRate = (float)floatValue.CurValue;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Get FrameRate Fail!" + ex.Message;
            }
        }

        public override void GetParamGain(out float gain, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            gain = 0;
            IFloatValue floatValue;
            try
            {
                int result = device.Parameters.GetFloatValue("Gain", out floatValue);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Get Gain Fail!";
                    return;
                }
                gain = (float)floatValue.CurValue;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Get Gain Fail!" + ex.Message;
            }
        }

        public override void GetParamPixelFormat(out EnumPixelFormat enumPixelFormat, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            enumPixelFormat = 0;
            IEnumValue enumValue;
            try
            {
                int result = device.Parameters.GetEnumValue("PixelFormat", out enumValue);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Get PixelFormat Fail!";
                    return;
                }
                enumPixelFormat = (EnumPixelFormat)Enum.Parse(typeof(EnumPixelFormat), enumValue.CurEnumEntry.Symbolic);
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Get PixelFormat Fail!" + ex.Message;
            }
        }

        public override void GetTriggerMode(out EnumTriggerMode enumTriggerMode, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            enumTriggerMode = EnumTriggerMode.None;
            try
            {
                int result = device.Parameters.GetEnumValue("TriggerMode", out IEnumValue enumValue);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Get TriggerMode Fail!";
                    return;
                }
                enumTriggerMode = (EnumTriggerMode)Enum.Parse(typeof(EnumTriggerMode), enumValue.CurEnumEntry.Symbolic);
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Get TriggerMode Fail!" + ex.Message;
            }
        }

        public override void GetTriggerSource(out EnumTriggerSource enumTriggerSource, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            enumTriggerSource = EnumTriggerSource.None;
            try
            {
                int result = device.Parameters.GetEnumValue("TriggerSource", out IEnumValue enumValue);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Get TriggerSource Fail!";
                    return;
                }
                enumTriggerSource = (EnumTriggerSource)Enum.Parse(typeof(EnumTriggerSource), enumValue.CurEnumEntry.Symbolic);
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Get TriggerSource Fail!" + ex.Message;
            }
        }

        public override void SetParamExposure(float exposureTime, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                int result = device.Parameters.SetEnumValue("ExposureAuto", 0);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set Exposure Auto Fail!";
                    return;
                }

                result = device.Parameters.SetFloatValue("ExposureTime", exposureTime);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set Exposure Time Fail!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Set Exposure Time Fail!" + ex.Message;
            }
        }

        public override void SetParamFrameRate(float frameRate, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                int result = device.Parameters.SetBoolValue("AcquisitionFrameRateEnable", true);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set AcquisitionFrameRateEnable Fail!";
                    return;
                }
                else
                {
                    result = device.Parameters.SetFloatValue("AcquisitionFrameRate", frameRate);
                    if (result != MvError.MV_OK)
                    {
                        ErrorCode = -1;
                        ErrorText = "Set Frame Rate Fail!";
                        return;
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Set FrameRate Fail!" + ex.Message;
            }
        }

        public override void SetParamGain(float gain, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                int result = device.Parameters.SetEnumValue("GainAuto", 0);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set Gain Auto Fail!";
                    return;
                }

                result = device.Parameters.SetFloatValue("Gain", gain);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set Gain Fail!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Set Gain Fail!" + ex.Message;
            }
        }

        public override void SetParamPixelFormat(EnumPixelFormat pixelFormat, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                if (isGrabbing)
                {
                    ErrorCode = -1;
                    ErrorText = "Can Not Set PixelFormat When Is Grabbing";
                    return;
                }

                string pF = pixelFormat.ToString();
                int result = device.Parameters.SetEnumValueByString("PixelFormat", pF);
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set PixelFormat failed!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Set PixelFormat Fail!" + ex.Message;
            }
        }

        public override void SetTriggerSource(EnumTriggerSource enumTriggerSource, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            enumTriggerSource = EnumTriggerSource.None;
            try
            {
                int result = device.Parameters.SetEnumValueByString("TriggerSource", enumTriggerSource.ToString());
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set TriggerSource failed!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Set TriggerSource Fail!" + ex.Message;
            }
        }
        public override void SetTriggerMode(EnumTriggerMode enumTriggerMode, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;

            try
            {
                int result = device.Parameters.SetEnumValueByString("TriggerMode", enumTriggerMode.ToString());
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set TriggerMode failed!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Set TriggerMode Fail!" + ex.Message;
            }
        }
        public override void StartGrab(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                if (!isGrabbing)
                {
                    int result = device.StreamGrabber.StartGrabbing();
                    if (result != MvError.MV_OK)
                    {
                        ErrorCode = -1;
                        ErrorText = "Start Grabbing Fail!";
                        return;
                    }
                    else
                    {
                        isGrabbing = true;
                    }
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Start Grabbing Fail!" + ex.Message;
            }
        }
        public override void StopGrab(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                // ch:停止采集 | en:Stop Grabbing
                int result = device.StreamGrabber.StopGrabbing();
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Stop Grab Fail!";
                    return;
                }
                else
                {
                    isGrabbing = false;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Stop Grab Fail!" + ex.Message;
            }
        }

        public override void SetAcquisitionContinuesMode(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
                int result = device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set AcquisitionMode Continuous Fail!";
                    return;
                }
                //关闭触发模式
                result = device.Parameters.SetEnumValueByString("TriggerMode", "Off");
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set TriggerMode Off Fail!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "Acquisition Continues Fail!" + ex.Message;
            }
        }

        public override void TriggerSoftwareOnce(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                // ch:打开触发模式 | en:Open Trigger Mode
                device.Parameters.SetEnumValueByString("TriggerMode", "On");

                // ch:触发源设为软触发 | en:Set trigger source as Software
                int result = device.Parameters.SetEnumValueByString("TriggerSource", "Software");
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set TriggerSource Software Fail!";
                    return;
                }
                // ch:触发命令 | en:Trigger command
                result = device.Parameters.SetCommandValue("TriggerSoftware");
                if (result != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "Set SetComman TriggerSoftware Fail!";
                    return;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "TriggerSoftwareOnce Fail!" + ex.Message;
            }
        }



        public override void SaveImageToFile(string filePath, IImage image, EnumImageFormatType imageFormatType, CFAMethod cfaMethod, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                ImageFormatInfo imageFormatInfo = new ImageFormatInfo();
                switch (imageFormatType)
                {
                    case EnumImageFormatType.Bmp:
                        imageFormatInfo.FormatType = ImageFormatType.Bmp;
                        break;
                    case EnumImageFormatType.Jpeg:
                        imageFormatInfo.FormatType = ImageFormatType.Jpeg;
                        break;
                    case EnumImageFormatType.Png:
                        imageFormatInfo.FormatType = ImageFormatType.Png;
                        break;
                    case EnumImageFormatType.Tiff:
                        imageFormatInfo.FormatType = ImageFormatType.Tiff;
                        break;
                    default:
                        break;
                }
                device.ImageSaver.SaveImageToFile(filePath, image, imageFormatInfo, cfaMethod);
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "SaveImageToFile Fail!" + ex.Message;
            }
        }

        public override void FeatureLoad(string filePath, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                if (isGrabbing)
                {
                    ErrorCode = -1;
                    ErrorText = "Camera Is Grabbing，Please Stop Grabbing And Try Again!";
                    return;
                }
                int ret = device.Parameters.FeatureLoad(filePath);
                if (ret != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "FeatureLoad Fail!";
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "FeatureLoad Fail!" + ex.Message;
            }
        }

        public override void FeatureSave(string filePath, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                if (isGrabbing)
                {
                    ErrorCode = -1;
                    ErrorText = "Camera Is Grabbing，Please Stop Grabbing And Try Again!";
                    return;
                }

                int ret = device.Parameters.FeatureSave(filePath);
                if (ret != MvError.MV_OK)
                {
                    ErrorCode = -1;
                    ErrorText = "FeatureSave Fail!";
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "FeatureSave Fail!" + ex.Message;
            }
        }

        /// <summary>
        /// 采集一张图像
        /// </summary>
        /// <param name="ErrorCode"></param>
        /// <param name="ErrorText"></param>
        /// <returns></returns>
        public override Bitmap AcquireOneFrameImage(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            int result;
            //图像变量置空
            OutBMPImage = null;
            try
            {
                //// ch:设置触发模式为off || en:set trigger mode as off
                // result = device.Parameters.SetEnumValue("TriggerMode", 0);
                //if (MvError.MV_OK != result)
                //{
                //    //Console.WriteLine("Set TriggerMode failed:{0:x8}", result);
                //    return OutBMPImage;
                //}

                //判断触发模式是否关闭
                device.Parameters.GetEnumValue("TriggerMode", out IEnumValue enumValue);
                if (enumValue.CurEnumEntry.Symbolic == EnumTriggerMode.On.ToString())
                {
                    ErrorCode = -1;
                    ErrorText = "AcquireOneFrameImage Fail! 触发模式(TriggerMode)为On，请将触发模式(TriggerMode)置为Off";
                    return OutBMPImage;
                if (!isGrabbing)
                {
                    result = device.StreamGrabber.StartGrabbing();
                    if (MvError.MV_OK != result)
                    {
                        // Console.WriteLine("Start grabbing failed:{0:x8}", result);
                        return OutBMPImage;
                    }
                    isGrabbing = true;
                }
                // ch:开启抓图 || en: start grab image
            }
            // ch:开启抓图 || en: start grab image


                IFrameOut frameOut;
                // ch:获取一帧图像 | en:Get one image
                result = device.StreamGrabber.GetImageBuffer(1000, out frameOut);

                OutBMPImage = frameOut.Image.ToBitmap() as Bitmap;

                //ch: 释放图像缓存 | en: Release image buffer
                result = device.StreamGrabber.StopGrabbing();
                if (MvError.MV_OK != result)
                {
                    // Console.WriteLine("Stop grabbing failed:{0:x8}", result);
                    return OutBMPImage;
                }
                isGrabbing = false;
            }
            isGrabbing = false;


                return OutBMPImage;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "AcquireOneFrameImage Fail!" + ex.Message;
                return OutBMPImage;
            }


        }

        /// <summary>
        /// ch:连续采图 | en:Continuous image acquisition
        /// </summary>
        /// <param name="_handle"></param>
        /// <param name="ErrorCode"></param>
        /// <param name="ErrorText"></param>
        public override void AcquireImageContinuous(IntPtr _handle, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;

            // ch:设置采集连续模式 | en:Set Continues Aquisition Mode
            int result = device.Parameters.SetEnumValueByString("AcquisitionMode", "Continuous");
            if (result != MvError.MV_OK)
            {
                ErrorCode = -1;
                ErrorText = "Set AcquisitionMode Continuous Fail!";
                return;
            }
            //关闭触发模式
            result = device.Parameters.SetEnumValueByString("TriggerMode", "Off");
            if (result != MvError.MV_OK)
            {
                ErrorCode = -1;
                ErrorText = "Set TriggerMode Off Fail!";
                return;
            }

            //开启线程连续采图
            new Thread(() =>
           {
               while (isGrabbing)
               {
                   IFrameOut frameOut;
                   int nRet = device.StreamGrabber.GetImageBuffer(1000, out frameOut);
                   if (MvError.MV_OK == nRet)
                   {
                       // =======判断句柄是否有效=====
                       if (_handle != IntPtr.Zero)
                       {
                           // ch:显示图像 | en:Display image
                           device.ImageRender.DisplayOneFrame(_handle, frameOut.Image);
                       }

                       //=====判断回调事件是否有订阅=====
                       if (EventGrabBackHIKImage != null)
                       {
                           // ch:回调事件返回海康接口的图像类型 | en:Callback event returns the HIK interface image type
                           EventGrabBackHIKImage(frameOut.Image);
                       }
                       //=====判断回调事件是否有订阅=====
                       if (EventGrabBackBitmapImage != null)
                       {
                           // ch:回调事件返回Bitmap图像 | en:Callback event returns Bitmap image
                           EventGrabBackBitmapImage(frameOut.Image.ToBitmap());
                       }
                   }

                   // ch: 释放图像缓存 | en: Release image buffer
                   device.StreamGrabber.FreeImageBuffer(frameOut);
               }
           }).Start();
        }


        public override void SetParamValueByFieldName(string fieldName, object value, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                HIKAreaScanCameraParameters HIKAreaScanCameraParameters = new HIKAreaScanCameraParameters();
                ICLVisionCameraParameterStruct parameterStruct = HIKAreaScanCameraParameters.GetFields().Where(x => x.ParameterName == fieldName).FirstOrDefault();
                switch (parameterStruct.ParameterType)
                {
                    case EnumCameraParameterType.Float:
                        float floatValue = Convert.ToSingle(value);
                        device.Parameters.SetFloatValue(fieldName, floatValue);
                        break;
                    case EnumCameraParameterType.Enum:
                        device.Parameters.SetEnumValueByString(fieldName, value.ToString());
                        break;
                    case EnumCameraParameterType.Integer:
                        device.Parameters.SetIntValue(fieldName, Convert.ToInt32(value));
                        break;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "SetParamByFieldName Fail!" + ex.Message;
            }
        }


        public override void GetParamValueByFieldName(string fieldName, out object value, out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            value = null;
            try
            {
                HIKAreaScanCameraParameters HIKAreaScanCameraParameters = new HIKAreaScanCameraParameters();
                ICLVisionCameraParameterStruct parameterStruct = HIKAreaScanCameraParameters.GetFields().Where(x => x.ParameterName == fieldName).FirstOrDefault();
                switch (parameterStruct.ParameterType)
                {
                    case EnumCameraParameterType.Float:
                        IFloatValue floatValue;
                        device.Parameters.GetFloatValue(fieldName, out floatValue);
                        value = floatValue.CurValue;
                        break;
                    case EnumCameraParameterType.Enum:
                        IEnumValue enumValue;
                        device.Parameters.GetEnumValue(fieldName, out enumValue);
                        value = enumValue.CurEnumEntry.Symbolic;
                        break;
                    case EnumCameraParameterType.Integer:
                        IIntValue intValue;
                        device.Parameters.GetIntValue(fieldName, out intValue);
                        value = intValue.CurValue;
                        break;
                }
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "GetParamByFieldName Fail!" + ex.Message;
            }
        }

        public override List<string> GetParamFieldNames(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                HIKAreaScanCameraParameters HIKAreaScanCameraParameters = new HIKAreaScanCameraParameters();
                return HIKAreaScanCameraParameters.GetFieldNames();
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "GetParamFieldNames Fail!" + ex.Message;
                return null;
            }
        }

        public override List<ICLVisionCameraParameterStruct> GetParamFields(out int ErrorCode, out string ErrorText)
        {
            ErrorCode = 0;
            ErrorText = string.Empty;
            try
            {
                HIKAreaScanCameraParameters HIKAreaScanCameraParameters = new HIKAreaScanCameraParameters();
                List<ICLVisionCameraParameterStruct> fields = HIKAreaScanCameraParameters.GetFields();
                for (int i = 0; i < fields.Count; i++)
                {
                    GetParamValueByFieldName(fields[i].ParameterName, out object value, out ErrorCode, out ErrorText);
                    fields[i].ParameterCurrentValue = value;
                }
                return fields;
            }
            catch (Exception ex)
            {
                ErrorCode = -1;
                ErrorText = "GetParamFields Fail!" + ex.Message;
                return null;
            }
        }
    }
}
